#ifndef VEHICLE_H
#define VEHICLE_H

#include "Game Engine\Header\Physics.h"

class Vehicle : public Physics
{
public:
	Vehicle();
	~Vehicle();

	virtual void		Init( ID3D10Device* device, btDynamicsWorld* world, std::wstring chassis,
							std::wstring wheels, ID3D10Effect* fx, ID3D10ShaderResourceView* cubeMap,
							float mass, bool useShadows = true );

	virtual void		SetForkLift( std::wstring lift, std::wstring forkSides,
							std::wstring forkBack, std::wstring connector );

	D3DXVECTOR3&		GetPosition();
	void				SetPosition( D3DXVECTOR3 pos );

	virtual void		Move( float dt ) = 0;

	void				SetRotation( Axis axis, float angle, bool clockwise = true );

	D3DXVECTOR3			GetRotation();
	void				SetGravity( D3DXVECTOR3 gravity );

	virtual void		Draw( D3DXMATRIX& lightViewProj );
	virtual void		DrawToShadowMap( ID3D10EffectMatrixVariable* mfxBuildShadowMapLightWVPVar,
							ID3D10EffectShaderResourceVariable* mfxBuildShadowMapDiffuseMapVar,
							ID3D10EffectPass* pass,	D3DXMATRIX& lightViewProj );

	void				ClientResetScene();

	D3DXMATRIX&			GetWorld();

	btRaycastVehicle*	GetVehicle();

protected:
	void				LockLiftHinge( void );
	void				LockForkSlider( void );

protected:
	ID3D10Device*		md3dDevice;

	D3DXMATRIX			mWorld;

	ID3D10ShaderResourceView*	mCubeMap;

	ID3D10Effect*		mFX;

	bool				mUseShadows;

	Mesh*				mChassisMesh;
	Mesh*				mWheelMesh;

	Mesh*				mLiftMesh;
	std::vector<Mesh*>	mForkMesh;
	Mesh*				mConnectMesh;

	D3DXVECTOR3			mPosition;

	btDynamicsWorld*	mDynamicsWorld;

	btAlignedObjectArray<btCollisionShape*> mCollisionShapes;

//----------------------------
	btRigidBody*		mCarChassis;

	btRigidBody*		mConnectBody;
	btSliderConstraint* mConnectSlider;

	btRigidBody*		mLiftBody;
	btVector3			mLiftStartPos;
	btHingeConstraint*	mLiftHinge;

	btRigidBody*		mForkBody;
	btVector3			mForkStartPos;
	btSliderConstraint* mForkSlider;
//----------------------------

	btRigidBody*		mPlaneChassis;

	btRaycastVehicle::btVehicleTuning	mTuning;

	btCompoundShape*	mCompound;

	btVehicleRaycaster*	mVehicleRayCaster;
	btRaycastVehicle*	mVehicle;
	btCollisionShape*	mWheelShape;

	btScalar			mDefaultContactProcessingThreshold;

	///btRaycastVehicle is the interface for the constraint that implements the raycast vehicle
	///notice that for higher-quality slow-moving vehicles, another approach might be better
	///implementing explicit hinged-wheel constraints with cylinder collision, rather then raycasts
	btVector3			mWheelDirectionCS0;
	btVector3			mWheelAxleCS;

	btScalar			mSuspensionRestLength;

	int					mRightIndex;
	int					mUpIndex;
	int					mForwardIndex;

	float				mEngineForce;

	float				mDefaultBreakingForce;
	float				mBreakingForce;

	float				mMaxEngineForce;
	float				mMaxBreakingForce;

	float				mVehicleSteering;
	float				mSteeringIncrement;
	float				mSteeringClamp;
	float				mWheelRadius;
	float				mWheelWidth;
	float				mWheelFriction;
	float				mSuspensionStiffness;
	float				mSuspensionDamping;
	float				mSuspensionCompression;
	float				mRollInfluence;

	float				mChassisHeight;
	float				mChassisWidth;
	float				mChassisLength;

	float				mConnectHeight;
	float				mConnectWidth;
	float				mConnectLength;

	float				mLiftWidth;
	float				mLiftLength;
	float				mLiftHeight;

	float				mMass;

	std::vector<float>	mForkWidth;
	std::vector<float>	mForkLength;
	std::vector<float>	mForkHeight;

	bool				mIsForkLift;
	UINT				mNumChassis;
	UINT				mNumLifts;
	UINT				mNumForks;

	float				mXAngle;
	float				mYAngle;
	float				mZAngle;
	float				mYaw;
	float				mPitch;
	float				mRoll;

	D3DXVECTOR3			mLook;
	float				mLooking;
};

#endif